import {
  DeleteOutlined,
  LoadingOutlined,
  PlusOutlined
} from '@ant-design/icons';
import { Button, Form, Image, message, Upload } from 'antd';
import React, { useRef, useState } from 'react';

import CropProductImageModal from '@/components/common/CropProductImageModal';
import { ImageToCropInfo } from '@/interface';
import { LayerInfoFE } from '@/pages/TemplateEditor/interface';

import { DeepPartial } from '../../../../../../../../../interface';
import {
  MAX_IMAGE_HEIGHT,
  MAX_IMAGE_SIZE,
  MAX_IMAGE_WIDTH,
  MIN_IMAGE_EDGE
} from '../../constant';
import {
  createURLForFile,
  getImgDimension,
  ifUploadImageSortEdgeTooSmallAfterResize
} from '../../utils';
import styles from './index.module.less';

interface Props {
  loading: boolean;
  layer: LayerInfoFE;
  setLoading: (value: boolean) => void;
  onChange: (values: DeepPartial<LayerInfoFE>) => void;
}

const ProductImageConfigs = ({
  layer,
  loading,
  onChange,
  setLoading
}: Props): JSX.Element => {
  const [imgPreviewVisible, setImgPreviewVisible] = useState(false);
  const [images, setImages] = useState<ImageToCropInfo[]>();
  const [open, setOpen] = useState(false);
  const timerRef = useRef<{ timer?: number }>({});
  const fileRef = useRef();

  const uploadProps = {
    showUploadList: false,
    withCredentials: true,
    accept: '.jpg, .png, .jpeg',
    beforeUpload: (file): boolean => {
      if (file.size > MAX_IMAGE_SIZE) {
        message.error('Wrong image size, no larger than 10 MB.');
        return false;
      }
    },
    customRequest: async (info): Promise<void> => {
      const { file } = info;
      const { name } = file;

      if (!file) {
        message.error('Upload fail.');
        return;
      }

      const src = createURLForFile(file);
      const { width, height } = await getImgDimension(src);

      if (width * height > MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT) {
        message.error(
          `The uploaded image cannot exceed an area of ${MAX_IMAGE_WIDTH}x${MAX_IMAGE_HEIGHT} pixels.`
        );
        return;
      }

      if (ifUploadImageSortEdgeTooSmallAfterResize(width, height)) {
        // sijia todo：临时文案
        message.error(
          `The uploaded image minimum edge can not smaller than ${MIN_IMAGE_EDGE} pixels after auto resize.`
        );
        return;
      }

      fileRef.current = file;

      setImages([
        {
          originWidth: width,
          originHeight: height,
          originSrc: src,
          name
        }
      ]);
      setOpen(true);
    }
  };

  const handleModalClose = (): void => setOpen(false);

  const handleCropSave = async (
    images: Array<ImageToCropInfo>
  ): Promise<void> => {
    const [image] = images;

    // 未有保存图片的时候，直接关闭弹窗
    if (!image) {
      setOpen(false);
      return;
    }

    const { width, height, name, src, originSrc, cropped, ratio } = image;

    setLoading(true);
    timerRef.current.timer = window.setTimeout(() => {
      message.loading({
        content: 'image uploading...',
        key: 'timer',
        duration: 0
      });
    });

    try {
      setOpen(false);
      const formData = new FormData();
      formData.append('file', fileRef.current);
      formData.append('image_type', 'cp_layer');
      const fileKey = String(Math.random());

      message.success({ content: 'Upload success.', key: 'timer' });
      onChange({
        src,
        width,
        height,
        data: {
          ratio,
          image: {
            name,
            cropped,
            fileKey,
            originSrc,
            isCropped: true
          }
        }
      });
    } catch (error) {
      message.error({ content: 'Upload fail.', key: 'timer' });
    } finally {
      setLoading(false);
      clearTimeout(timerRef.current.timer);
    }
  };

  const handleDelete = (): void => {
    onChange({
      src: '',
      width: 0,
      height: 0,
      data: {
        image: {
          name: ''
        }
      }
    });
  };

  return (
    <div>
      <Form.Item className={styles.container}>
        <div className={styles['upload-title']}>Image</div>
        {layer.src ? (
          <div className={styles['upload-img']}>
            <Image
              src={layer.src}
              alt="avatar"
              style={{ width: '100%', height: '100%' }}
              preview={{
                visible: imgPreviewVisible,
                onVisibleChange: (visible): void =>
                  setImgPreviewVisible(visible),
                mask: (
                  <div
                    onClick={(e): void => e.stopPropagation()}
                    className={styles['uploaded-image-btn-group']}
                  >
                    <Button
                      type="text"
                      icon={<DeleteOutlined />}
                      className={styles['uploaded-image-btn']}
                      onClick={handleDelete}
                    />
                  </div>
                )
              }}
            />
          </div>
        ) : (
          <Upload
            {...uploadProps}
            listType="picture-card"
            className={styles.upload}
          >
            <Button
              type="text"
              disabled={loading}
              className={styles['upload-btn']}
              icon={loading ? <LoadingOutlined /> : <PlusOutlined />}
            >
              <span>Upload</span>
            </Button>
          </Upload>
        )}
      </Form.Item>
      <CropProductImageModal
        open={open}
        images={images}
        onSave={handleCropSave}
        onClose={handleModalClose}
      />
    </div>
  );
};

export default ProductImageConfigs;
